/**
 * 
 * This class provides a modified version (a subclass) of the GeoPoint class.
 * 
 * The public constructor provides a simplified way to use both the longitude and the latitude in
 * the way they were received from the server.
 * 
 */
package com.mhsoft.fenak.utils;

import com.google.android.maps.GeoPoint;

import android.content.Context;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.net.wifi.WifiManager;
import android.os.Bundle;
import android.util.Log;

public final class MyGeoClass extends GeoPoint{

	private double longitude, latitude;

	static private Location location;
	
	private static LocationManager locManager;
	
	public MyGeoClass(int latitudeE6, int longitudeE6) {
		super(latitudeE6, longitudeE6);
	}

	public MyGeoClass(double latitude, double longitude){
		super((int)(latitude*1E6), (int)(longitude*1E6));
		
		this.latitude = latitude;
		this.longitude = longitude;
	}

	public double getLongitude() {
		return longitude;
	}

	public void setLongitude(double longitude) {
		this.longitude = longitude;
	}

	public double getLatitude() {
		return latitude;
	}

	public void setLatitude(double latitude) {
		this.latitude = latitude;
	}

	/**
	 * Used to get the GeoPoint of the current location of the user using the
	 * GPS provider or the Network provider.
	 * 
	 * @param context
	 * @return (A GeoPoint) representing the current location of the user OR
	 *         (Null) in case of network covering and the GPS provider is
	 *         disabled.
	 */
	public static void prepareLocation(Context context) {
		
		WifiManager wifi = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
		
		location = null;
		
		locManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
		
		locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locationListener);

		locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
		
		if(locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER) && wifi.isWifiEnabled()){
			
			location = locManager.getLastKnownLocation(LocationManager.NETWORK_PROVIDER);
		}

		if (location == null) {
			
			if(locManager.isProviderEnabled(LocationManager.GPS_PROVIDER)){
				
				location = locManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
			}
		}
	}

	public static Location getMyLocation(){
		
		// to make sure that (accuracy, longitude and latitude) are acquired from the same value
		//		as (location) may change when the listener receives a new fix ...
		return location;
	}
	
	private static LocationListener locationListener = new LocationListener() {
		@Override
		public void onStatusChanged(String provider, int status, Bundle extras) {
		}

		@Override
		public void onProviderEnabled(String provider) {
		}

		@Override
		public void onProviderDisabled(String provider) {
			// updateWithNewLocation(null);
		}

		@Override
		public void onLocationChanged(Location location) {
			
			updateWithNewLocation(location);
		}
	};

	private static void updateWithNewLocation(Location currentLocation) {
		
		if (location != null) {
			
			if(isCurrentLocationBetter(currentLocation, location)){
				
				// this line is of no use for now as when this line is executed, the latitude and the 
				// 		longitude would have been already sent ...
				location = currentLocation;
			}
		} 
		else {
			
			Log.d("Location!!!!!!!!!!!!!!!!1", "No location found");
		}
	}
	
	static void removeLocationUpdates(){
		
		locManager.removeUpdates(locationListener);
		Log.d("UNREGISTERED", "###############################");
	}
	
	private static boolean isCurrentLocationBetter(Location currentLocation, Location previousLocation){
		
		if (previousLocation == null) {

	        return true;
	    }
		
		// Check whether the new location fix is newer or older
	    long timeDelta = currentLocation.getTime() - previousLocation.getTime();
	    boolean isNewer = timeDelta > 0;
	    
	    // Check whether the new location fix is more or less accurate
	    int accuracyDelta = (int) (currentLocation.getAccuracy() - previousLocation.getAccuracy());
	    boolean isLessAccurate = accuracyDelta > 0;
	    boolean isMoreAccurate = accuracyDelta < 0;
	    boolean isSignificantlyLessAccurate = accuracyDelta > 150;
	    
	    // Determine location quality using a combination of timeliness and accuracy
	    if (isMoreAccurate) {
	    	
	        return true;
	    } 
	    else if (isNewer && !isLessAccurate) {
	    	
	        return true;
	    } 
	    else if (isNewer && !isSignificantlyLessAccurate) {
	    	
	        return true;
	    }
	    
	    return false;
	}

}
